/*
 * @Author: hongbin
 * @Date: 2022-09-04 22:25:16
 * @LastEditors: hongbin
 * @LastEditTime: 2022-09-15 21:07:07
 * @Description: 森林
 */
import THREE from "../../";
import { guiTestPosition } from "./../../utils/gui";
import MakeGrass from "../../utils/MakeGrass";
import { setOneSideMaterial, sortMeshChildren, transparentModel } from "../../helper";
import { loadGltf } from "../../helper/loaderHelper";
import { setActerPosition, setActerRotate } from "../../object";
import { MonitorArray, TPlanet } from "../../types";
import { _undergroundMesh } from "../../worker/helper/undergroundCheck";
import { createTreasureChest } from "./TreasureChest";

// 有体积的即 需要碰撞检测的
export const withVolume: MonitorArray<THREE.Object3D> = [];
//整个星球的物体
const objects = new THREE.Group();
// const floorHeight = 60;
const mustBeDetected = [] as THREE.Mesh[];
withVolume.push = (...items: typeof withVolume[number][]) => {
    if (typeof withVolume.monitoringChanges === "function") withVolume.monitoringChanges(...items);
    return Array.prototype.push.call(withVolume, ...items);
};
/**
 * home中需要逐帧执行的操作
 */
const ticksClip: Array<() => void> = [];
const ticks = () => {
    ticksClip.forEach((tick) => tick());
};

/**
 * 森林星球
 */
function genSphere() {
    const geometry = new THREE.SphereGeometry(330, 32, 32);
    // const geometry = new BoxGeometry(550, 550, 550, 100, 100, 100);
    const material = new THREE.MeshBasicMaterial({
        // ...coastSandRocksTexture,
        // envMap: environmentMapTexture,
        side: THREE.DoubleSide,
        color: "#275819",
        transparent: true,
        opacity: 0.2,
    });
    //gui.add(material, "opacity", 0, 1).onChange(window.render);
    const sphere = new THREE.Mesh(geometry, material);
    return sphere;
}

objects.position.set(880, 0, 0);

/**
 * ejector(喷射器)
 */
const loadEjector = () => {
    loadGltf("api/glb?name=ejector.glb")
        .then(({ scene }) => {
            scene.name = "ejector";
            // acterWrap.add(scene);
            objects.add(scene);
            scene.position.set(32, -1.5, -13);
            scene.rotateY(-Math.PI / 2);
            scene.scale.set(2, 2, 2);
            scene.userData.clearState = () => {
                scene.position.set(0, 0, 0);
                scene.rotateY(Math.PI / 2);
                scene.scale.set(1, 1, 1);
            };
        })
        .catch((err) => {
            console.log("err", err);
        });
};

/**
 * 初始化星球物体
 */
const init = () => {
    const planet = genSphere();
    planet.name = "forest";
    planet.position.y = -20;
    forest.planet = planet;
    objects.add(planet);
    //TODO 加载模型
    loadEjector();
    forest.mustBeDetected.push(planet);

    // setActerPosition(new THREE.Vector3(845, 20, 101));
    // setActerRotate(new THREE.Vector3(0, Math.PI / 2, 0));

    guiTestPosition(objects, 50);
};

objects.add(_undergroundMesh);

const underground = {
    needCalculate: (acterYAxisHeight: number) => {
        return acterYAxisHeight < 15;
    },
};

const forest = {
    init,
    name: "forest",
    withVolume,
    objects,
    ticks,
    mustBeDetected,
    polarAngle: { min: Math.PI / 2 },
    underground,
    fallIntoFloor: (upDistance, velocity) => {
        velocity!.y = 170;
        return upDistance;
    },
} as TPlanet;

export default forest;

export const treasureChestGroup = new THREE.Group();

export const handleParseTreasureChest = (object: THREE.Object3D) => {
    const treasureChest = object.getObjectByName("treasureChest");
    const treasureChestCover = object.getObjectByName("treasureChestCover");
    const floorEffect = object.getObjectByName("floorEffect");
    if (!treasureChest || !treasureChestCover || !floorEffect) return;
    transparentModel(floorEffect as THREE.Mesh);
    treasureChestGroup.add(treasureChest, treasureChestCover, floorEffect);
    createTreasureChest(objects, withVolume);
};

export const handleParseGrove = (object: THREE.Object3D) => {
    withVolume.push(object);
    objects.add(object);
    object.position.x = -70;
    object.position.y = 5;

    setOneSideMaterial(object, "BackSide");
};

export const handleParsePlain = (object: THREE.Object3D) => {
    objects.add(object);
    const plain = object.getObjectByName("plain") as THREE.Mesh;
    const [r, p] = sortMeshChildren(plain.children as THREE.Mesh[]);
    setOneSideMaterial(p, "FrontSide");
    plain.scale.set(1.6, 2, 2);
    plain.position.y = 5;
    plain.position.x = -85;
    // withVolume.push(object);
    forest.mustBeDetected.push(r, p);

    const grass = new MakeGrass(objects, r, 10000);
    grass.instancedMesh.scale.copy(plain.scale);
    grass.instancedMesh.position.copy(plain.position);
    // grass.instancedMesh.matrix.decompose(plain.position, plain.quaternion, plain.scale);
    ticksClip.push(() => {
        //@ts-ignore
        grass && grass.update();
    });
};
